#!/bin/bash

# Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT)
# Copyright (C) 2010 Daniel Krieg
# All rights reserved.
#
# This software may be modified and distributed under the terms of the
# BSD-3-Clause license. See the accompanying LICENSE file for details.


### call "yarp name list" and extract all available ports
_get_yarp_ports() {
    echo $(yarp name list 2>/dev/null | grep registration | awk '{print $3 }'| grep ^\/ )
}

### call "yarp run --on 'server' --ps" and extract all available tags
_get_yarprun_tags() {
    echo $(yarp run --on $1 --ps 2>&1 | grep "^(pid" | sed  's/(//g;s/)//g' | awk '{print $4 }' )
}

_get_yarp_help(){
echo $(yarp help 2>/dev/null| awk 'NR>=4 {print $1}' )
}

_get_yarp_carriers(){
echo $(yarp connect --list-carriers 2>/dev/null)
}

_get_yarp_plugins(){
echo $(yarp plugin --list 2>/dev/null)
}


_yarp()
{
    COMPREPLY=()

    # check if bash completion version is 1.2 or higher
    if type _get_comp_words_by_ref > /dev/null 2>&1 ;
    then bc1_2=true;
    else bc1_2=false;
    fi;

    if $bc1_2 ;
    then
        _get_comp_words_by_ref -n : cur prev words cword
        COMP_WORDS=$words
        COMP_CWORD=$cword ;
    else
         local cur=$(_get_cword) ;
    fi;
    local command="${COMP_WORDS[1]}"
    local cmds=$(_get_yarp_help)
    local connectopts=(--persist --persist-to --persist-from --list-carriers --help)
    local pluginopts=(--help --list --all --search-path)

    completion=""
    if [ $COMP_CWORD -eq 1 ]; then
        ### first option => possible commands
        completion="${cmds}"
    else
        case "${command}" in
            connect)
                local secondArg="${COMP_WORDS[2]}"
                if [ $COMP_CWORD -eq 2 ]; then
                    ### complete source port
                    completion="${connectopts[@]} $(_get_yarp_ports)"
                elif [ $COMP_CWORD -eq 3 ]; then
                    ### complete destination port
                    completion=$(_get_yarp_ports)
                elif [ $COMP_CWORD -eq 4 ]; then
                    if [[ ${connectopts[*]} =~ "${secondArg}" ]]; then
                        completion=$(_get_yarp_ports)
                    else
                        completion=$(_get_yarp_carriers)
                    fi
                elif [[ $COMP_CWORD -eq 5 &&  ${connectopts[*]} =~ "${secondArg}"  ]]; then
                    completion=$(_get_yarp_carriers)
                fi
                ;;
            disconnect)
                if [ $COMP_CWORD -le 3 ]; then
                    ### complete source and destination ports
                    completion=$(_get_yarp_ports)
                fi
                ;;
            read)
                if [ $COMP_CWORD -eq 3 ]; then
                    ### complete destination port
                    completion=$(_get_yarp_ports)
                fi
                ;;
            write)
                if [ $COMP_CWORD -eq 3 ]; then
                    ### complete destination port
                    completion=$(_get_yarp_ports)
                fi
                ;;
            run)
                ### handle with yarprun completion
                ### offset of 1 for additional command
                _yarprun 1
               ;;
            context)
                _yarpcontext
                ;;
            robot)
                _yarprobot
                ;;
            exists|ping|rpc|terminate|wait)
                if [ $COMP_CWORD -eq 2 ]; then
                    completion=$(_get_yarp_ports)
                fi
                ;;
            detect)
                if [ $COMP_CWORD -eq 2 ]; then completion="--write"; fi ;;
            name)
                ### TODO: add more nameserver commands if needed
                if [ $COMP_CWORD -eq 2 ]; then completion="list"; fi ;;
            conf)
                if [ $COMP_CWORD -eq 2 ]; then completion="--clean"; fi ;;
            plugin)
                if [ $COMP_CWORD -eq 2 ]; then
                    completion="${pluginopts[@]} $(_get_yarp_plugins)"
                fi
                ;;
            *)
                ;;
        esac

    fi
    COMPREPLY=( $(compgen -W "${completion}" -- ${cur}) )
    if $bc1_2 ;
    then __ltrim_colon_completions "$cur"
    fi;

    return 0

}

_yarprun() {
    COMPREPLY=()
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local prev="${COMP_WORDS[COMP_CWORD-1]}"
    if [ $COMP_CWORD -ge 2 ]; then
        local pprev="${COMP_WORDS[COMP_CWORD-2]}"
    fi
    local command="${COMP_WORDS[1]}"
    local run_cmds1="--cmd --as --geometry --hold --stdio --workdir"
    local run_cmds2="--kill --sigterm --sigtermall --ps --isrunning --exit"

    completion=""

    ### check offset (if called from "yarp run" instead of "yarprun")
    ### default 0
    offset=${1:-0}

    if [ $COMP_CWORD -eq $((1+$offset)) ]; then
        ### first options (either start new server or send command to exisiting one)
        completion="--on --server"
    else
        if [ $COMP_CWORD -ge $((2+$offset)) -a "${COMP_WORDS[$((1+$offset))]}" == "--on" ]; then
            server=${COMP_WORDS[$((2+$offset))]}
            case "$prev" in
                "--on"|"--stdio")
                    ### complete server or stdio port
                    completion=$(_get_yarp_ports)
                    ;;
                "--kill"|"--sigterm"|"--isrunning")
                    ### complete tags running on server
                    completion=$(_get_yarprun_tags $server)
                    ;;
                "--hold")
                    completion="$run_cmds1"
                    ;;
                *)
                    ### options with user input
                    case "$pprev" in
                        ### complete after user input has been entered
                        "--on")
                            completion="$run_cmds1 $run_cmds2"
                            ;;
                        "--cmd"|"--geometry"|"--stdio"|"--as"|"--workdir")
                            completion="$run_cmds1"
                            ;;
                    esac
                    ;;
            esac
        fi
    fi

    COMPREPLY=( $(compgen -W "${completion}" -- ${cur}) )

    return 0
}

_yarpserver(){
    COMPREPLY=()
    local cur="${COMP_WORDS[COMP_CWORD]}"

    completion=""

    ### check offset (if called from "yarp server" instead of "yarpserver")
    ### default 0
    offset=${1:-0}

    if [ $COMP_CWORD -eq $((1+$offset)) ]; then
        completion=$(echo $(yarpserver --help | grep -o "^  --\S*" |  sed 's/ //g' | sort ) )
    fi

    COMPREPLY=( $(compgen -W "${completion}" -- ${cur}) )

    return 0
}

_get_all_contexts() {

    for x in `yarp-config context --list | grep "^[^\*]" | sort | uniq`;
       do echo ${x} ;
    done
}

_get_user_contexts() {

    for x in `yarp-config context --list --user| grep "^[^\*]" | sort | uniq`;
       do echo ${x} ;
    done
}

_get_installed_contexts() {

    for x in `yarp-config context --list --installed| grep "^[^\*]" | sort | uniq`;
       do echo ${x} ;
    done
}

_yarpcontext() {
    COMPREPLY=()
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local prev="${COMP_WORDS[COMP_CWORD-1]}"
    local command="${COMP_WORDS[2]}"
    local opts="--where --import --remove --diff --diff-list --merge --list --help --import-all"

    completion=""
    if [ $COMP_CWORD -eq 2 ]; then
        ### first options
        completion=$opts
    else
        case "$prev" in
            "--where")
                completion=$(_get_all_contexts)
                ;;
            "--import")
                completion=$(_get_installed_contexts)
                ;;
            "--remove"|"--diff"|"--merge")
                completion=$(_get_user_contexts)
                ;;
            "--list")
                completion="--user --sysadm --installed"
                ;;
            *)
                case "$command" in
                "--import" )
                    local contextName="${COMP_WORDS[3]}"
                    local directories
                    for x in `yarp-config context --where $contextName --installed| grep "^[^\*]" | sort | uniq`;
                       do directories="${directories[@]} $x"
                    done
                    for d in ${directories}
                       do completion+="$(find "${d}" -mindepth 1 -printf '%P\n')"
                    done
                    ;;
                "--remove"|"--merge")
                    local contextName="${COMP_WORDS[3]}"
                    local directories
                    for x in `yarp-config context --where $contextName --user| grep "^[^\*]" | sort | uniq`;
                       do directories="${directories[@]} $x"
                    done
                    for d in ${directories}
                       do completion+="$(find "${d}" -mindepth 1 -printf '%P\n')"
                    done
                    ;;
                *)
                ;;
            esac
            ;;
        esac
    fi

    COMPREPLY=( $(compgen -W "${completion}" -- ${cur}) )

    return 0
}


_get_all_robots() {

    for x in `yarp-config robot --list | grep "^[^\*]" | sort | uniq`;
       do echo ${x} ;
    done
}

_get_user_robots() {

    for x in `yarp-config robot --list --user| grep "^[^\*]" | sort | uniq`;
       do echo ${x} ;
    done
}

_get_installed_robots() {

    for x in `yarp-config robot --list --installed| grep "^[^\*]" | sort | uniq`;
       do echo ${x} ;
    done
}


_yarprobot() {
    COMPREPLY=()
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local prev="${COMP_WORDS[COMP_CWORD-1]}"
    local command="${COMP_WORDS[2]}"
    local opts="--where --current --import --remove --diff --diff-list --merge --list --help --import-all"

    completion=""
    if [ $COMP_CWORD -eq 2 ]; then
        ### first options
        completion=$opts
    else
        case "$prev" in
            "--where")
                completion=$(_get_all_robots)
                ;;
            "--import")
                completion=$(_get_installed_robots)
                ;;
            "--remove"|"--diff"|"--merge")
                completion=$(_get_user_robots)
                ;;
            "--list")
                completion="--user --sysadm --installed"
                ;;
            *)
            case "$command" in
                "--import" )
                    local robotName="${COMP_WORDS[3]}"
                    local directories
                    for x in `yarp-config robot --where $robotName --installed| grep "^[^\*]" | sort | uniq`;
                       do directories="${directories[@]} $x"
                    done
                    for d in ${directories}
                       do completion+="$(find "${d}" -mindepth 1 -printf '%P\n')"
                    done
                    ;;
                "--remove"|"--merge")
                    local robotName="${COMP_WORDS[3]}"
                    local directories
                    for x in `yarp-config robot --where $robotName --user| grep "^[^\*]" | sort | uniq`;
                       do directories="${directories[@]} $x"
                    done
                    for d in ${directories}
                       do completion+="$(find "${d}" -mindepth 1 -printf '%P\n')"
                    done
                    ;;
                *)
                ;;
            esac
            ;;
        esac

    fi
    COMPREPLY=( $(compgen -W "${completion}" -- ${cur}) )

    return 0
}

_yarpconfig() {
    COMPREPLY=()
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local prev="${COMP_WORDS[COMP_CWORD-1]}"
    local command="${COMP_WORDS[1]}"
    local opts="context robot --help --namespace --nameserver --version"
    completion=""
    if [ $COMP_CWORD -eq 1 ]; then
        ### first options
        completion=$opts
    else
        case "$command" in
            "context")
                _yarpcontext
                ;;
            "robot")
                _yarprobot
                ;;
            *)
            ;;
        esac
    fi
    COMPREPLY=( $(compgen -W "${completion}" -- ${cur}) )

    return 0
}

complete -F _yarpconfig yarp-config
complete -F _yarp yarp
complete -F _yarprun yarprun
complete -F _yarpserver yarpserver
